/** 
 * MemoryPane.java
 * @author Lex
 * 2007-8-17 ����02:52:05
 */
package org.lex.swing.widgets;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.Timer;
import javax.swing.UIManager;

import org.lex.utils.text.SizeFormat;


/**
 * �쿴/����������ڴ��ʹ�����
 */
public class MemoryPane extends JComponent {
	private long used = 0L;
	private long total = 0L;
	private String paintString = "";
	// ���¼��
	private int interval = 1000;
	private Timer updateTimer = null;

	public MemoryPane() {
		super();
		// ==============================================
		this.updateTimer = new Timer(interval, null);
		this.updateTimer.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				repaint();
			}
		});
		this.updateTimer.start();
		this.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				new Thread(new Runnable() {
					public void run() {
						Runtime.getRuntime().runFinalization();
						Runtime.getRuntime().gc();
					}
				}).start();
			}
		});
	}

	public Color getTextColor() {
		return UIManager.getColor("ProgressBar.selectionBackground");
	}

	public Color getForeground() {
		return UIManager.getColor("ProgressBar.foreground");
	}

	public Color getBackground() {
		return UIManager.getColor("ProgressBar.background");
	}

	@Override
	public Dimension getMaximumSize() {
		Dimension prefs = this.getPreferredSize();
		prefs.width = Short.MAX_VALUE;
		return prefs;
	}

	@Override
	public Dimension getMinimumSize() {
		Dimension prefs = this.getPreferredSize();
		prefs.height = 10;
		return prefs;
	}

	@Override
	public Dimension getPreferredSize() {
		Dimension size;
		Insets insets = this.getInsets();
		FontMetrics fm = this.getFontMetrics(this.getFont());
		size = new Dimension(160, 12);
		// Ensure that the progress string will fit
		int stringWidth = fm.stringWidth(paintString);
		if (stringWidth > size.width) {
			size.width = stringWidth;
		}
		// This uses both Height and Descent to be sure that
		// there is more than enough room for everything.
		int stringHeight = fm.getHeight() + fm.getDescent();
		if (stringHeight > size.height) {
			size.height = stringHeight;
		}
		size.width += insets.left + insets.right;
		size.height += insets.top + insets.bottom;
		return size;
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		this.paintMemory((Graphics2D) g);
	}

	private void paintMemory(Graphics2D g2) {
		this.total = Runtime.getRuntime().totalMemory();
		this.used = total - Runtime.getRuntime().freeMemory();
		Insets insets = this.getInsets();
		int actualWidth = this.getWidth() - (insets.right + insets.left);
		int actualHeight = this.getHeight() - (insets.top + insets.bottom);
		// amount of progress to draw
		int amount = Math.round(actualWidth * (float) used / total);
		// ==========================
		Rectangle2D.Float tmp = new Rectangle2D.Float();
		// clear previous drawing
		tmp.setRect(insets.left, insets.top, actualWidth, actualHeight);
		g2.setColor(this.getBackground());
		g2.fill(tmp);
		// draw new status
		tmp.width = amount;
		g2.setColor(this.getForeground());
		g2.fill(tmp);
		// draw border
		tmp.width = actualWidth;
		g2.setColor(this.getTextColor());
		g2.draw(tmp);
		// draw text
		paintString = SizeFormat.autoFormat(used) + " / " + SizeFormat.autoFormat(total);
		Point loc = getStringPlacement(paintString, insets.left, insets.top, actualWidth, actualHeight);
		g2.setColor(this.getTextColor());
		g2.setFont(this.getFont());
		g2.drawString(paintString, loc.x, loc.y);
	}

	/**
	 * Designate the place where the progress string will be painted. This
	 * implementation places it at the center of the progress bar (in both x and
	 * y).
	 */
	protected Point getStringPlacement(String str, int x, int y, int width, int height) {
		FontMetrics fm = this.getFontMetrics(this.getFont());
		int strWidth = fm.stringWidth(str);
		Point p = new Point(x, y);
		p.x += Math.round((width - strWidth) / 2);
		p.y += (height + fm.getAscent() - fm.getLeading() - fm.getDescent()) / 2;
		return p;
	}
}
